const glob = require('glob');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
const { VueLoaderPlugin } = require('vue-loader');
const webpack = require('webpack');

// 动态构造page.entry
const pageEntries = {}
const HtmlWebpackPluginList = [];
// 获取app/pages目录下所有入口文件(enry.xx.js)
glob.sync(path.resolve(process.cwd(), './app/pages/**/entry.*.js')).forEach(file => {
    const entryName = path.basename(file, '.js');
    pageEntries[entryName] = file;
    HtmlWebpackPluginList.push(new HtmlWebpackPlugin({
      // 模板路径
      filename: path.resolve(process.cwd(), './app/public/dist/',`${entryName}.tpl`),
      // 指定使用的模版文件
      template: path.resolve(process.cwd(), './app/view/entry.tpl'),
      // 要注入的代码块
      chunks:[entryName]
    }))
});;

/**
 * webpack 基础配置
 * */ 
module.exports = {
  // 入口配置
  entry: pageEntries,
  // 模块解析配置
  module:{
    rules:[{
      test: /\.vue$/,
      use:{
        loader: 'vue-loader'
      }
    },{
      test: /\.js$/,
      include:[path.resolve(process.cwd(), './app/pages')],
      use:{
        loader: 'babel-loader'
      }
    },{
      test:/\.(png|jpe?g|gif|svg)(\?.+)?$/,
      use:[{
        loader: 'url-loader',
        options:{
          limit: 300,
          esModule: false
        }
      }]
    },{
      test:/\.css$/,
      use:['style-loader','css-loader']
    },{
      test:/\.less$/,
      use:['style-loader','css-loader','less-loader']
    },{
      test:/\.(eot|svg|ttf|woff|woff2)(\?\S)?$/,
      use:['file-loader']
    }]
  },
  // 产输出配置路径,因为开发和生产环境输出不一致,所以在各自环境中自行配置
  output: {
    filename: 'js/[name]_[chunkhash:8].bundle.js',
    path: path.join(process.cwd(), './app/public/dist/prod'),
    publicPath:'/dist/prod',
    crossOriginLoading: 'anonymous'
  },
  // 配置模块解析的具体行为(定义 webpack，如何找到并解析具体模块的路径)
  resolve:{
    extensions: ['.js', '.vue', '.less','.css'],
    alias:{
      $page:path.resolve(process.cwd(), './app/pages'),
      $common:path.resolve(process.cwd(), './app/pages/common'),
      $widgets:path.resolve(process.cwd(), './app/pages/widgets'),
      $store:path.resolve(process.cwd(), './app/pages/store'),
    }
  },
  // 插件配置
  plugins:[
    // 处理.vue文件 这个是必须的
    // 他只能将你定义过其他规则复制并且应用到 .vue文件当中
    // 例如，如果有一条匹配规则/\.js$/的规则，那么他会应用到.vue文件中的script板块中
    new VueLoaderPlugin(),
    // 把第三方库暴露到window context下
    new webpack.ProvidePlugin({
      Vue:'vue'
    }),
    // 定义全局常量
    new webpack.DefinePlugin({
      __VUE_OPTIONS_API__: true, //支持vue解析option api
      __VUE_PROD__DEVTOOLS: false,//禁用VUE调试工具
      __VUE_PROD_HYDRATION__: false //禁用生产环境显示“水合”信息
    }),
    ...HtmlWebpackPluginList
  ],
  // 配置打包输出优化（配置代码分割，模块合并，Tree-shaking，压缩等策略）
  optimization:{
    /**
     * 把js 文件打包成三种类型
     * 1.vendor 第三方lib库 基本不会改动，除非依赖版本升级
     * 2.common 业务组件代码公共部分抽取出来改动较少
     * 3.entry.{page} 不用页面entry里的业务的差异部分会经常改动
     * 目的：把改动和引用频率不一样的js区分出来，以达到更好利用浏览器缓存的效果
     * */ 
    splitChunks:{
      chunks:'all',//对同步和异步模块都进行分割
      maxAsyncRequests:10,//每次异步加载的最大平行请求数
      maxInitialRequests:10,//入口点最大并行请求数
      cacheGroups:{
        vendor:{ //第三方依赖
          test: /[\\/]node_modules[\\/]/,
          name:'vendor', //模块名称
          priority:20, //优先级数字越大优先级越高
          enforce:true,//强制执行
          reuseExistingChunk:true,//复用已有的公共 chunk
        },
        // 2.将业务中公共的代码打包到common.js中
        common:{
          name:'common', //模块名称
          minChunks:2, //被两处引用被归类为公共模块
          minSize:1,//最小分割文件大小 （1 byte）
          priority:-20, //优先级数字越大优先级越高
          reuseExistingChunk:true,//复用已有的公共 chunk
        }
       
      }
    },
    runtimeChunk:true
  }
}
